/***********************************
* Name: MethodAsmCodeGen.java
* Date: Oct 15, 2010
* @author martin
* Description:
***********************************/

package asmCodeGen;

import interCodeGen.*;
import decaf.*;
import java.util.LinkedList;

public class MethodAsmCodeGen {
    
    private LinkedList<AsmCode> code = new LinkedList<AsmCode>();
    private MethodInterCodeGen interMethod;
    private LinkedList<BasicBlock> bloques = new LinkedList<BasicBlock>();
    private LinkedList<Cod3Dir> cod3dir;
    private Method method;

    private int ganancia_de_pila = 0;

    /***********************************
     * constructor
     ***********************************/
    public MethodAsmCodeGen(MethodInterCodeGen inter_code){
        this.interMethod = inter_code;
        this.method = this.interMethod.method;

        cod3dir = new LinkedList<Cod3Dir>();

        for(int i=0;i<this.interMethod.codigo.size()-4;i++){
            cod3dir.add(this.interMethod.codigo.get(i));
        }
        while(true){
            Cod3Dir a = cod3dir.getFirst();
            if(a instanceof interCodeGen.InterPlane){
                cod3dir.removeFirst();
                break;
            }
            else{
                cod3dir.removeFirst();
            }
        }
        
        //createBlocks(cod3dir);
        //System.out.println("cantidad de blocks: "+this.bloques.size());
    }

    /***********************************
     * @return the code
     ***********************************/
    public LinkedList<AsmCode> getCode() {
        return code;
    }

    /***********************************
     * addToCode
     * @param code to add
     ***********************************/
    private void addToCode(AsmCode line){
        this.code.add(line);
    }

    /***********************************
     * isTemporal
     * @param String temp
     * @return boolean saying if is temporal
     ***********************************/
    private boolean isTemporal(String temp){
        return MethodInterCodeGen.isTemporal(temp);
    }

    /***********************************
     * addAllToCode
     * @param code to add
     ***********************************/
    private void addToCodeAll(LinkedList<AsmCode> lines){
        this.code.addAll(lines);
    }

    /***********************************
     * createBlocks
     * @param cod3dir
     ***********************************/
    private void createBlocks(LinkedList<Cod3Dir> cod3dir) {

        LinkedList<Cod3Dir> blocks = new LinkedList<Cod3Dir>();
        if(cod3dir.size()!=0){
            blocks.add(cod3dir.get(0));//la primera instrucción es líder
        }

        for(int i=1; i<cod3dir.size(); i++){
            Cod3Dir a = cod3dir.get(i);

            if(a instanceof interCodeGen.InterEtiqueta){
                if(blocks.size()!=0){
                    this.bloques.add(new BasicBlock(blocks));//se agrega lo que llevaba
                    blocks = new LinkedList<Cod3Dir>();//empieza el nuevo bloque básico
                }
                //la etiqueta es una instrucción líder
                blocks.add(a);
            }
            else if(a instanceof interCodeGen.InterSalto || a instanceof interCodeGen.InterCondicional)
            {
                blocks.add(a);
                this.bloques.add(new BasicBlock(blocks));//se agrega lo que llevaba
                blocks = new LinkedList<Cod3Dir>();//empieza el nuevo bloque básico

            }
            else{
                blocks.add(a);
            }
        }

        if(blocks.size()!=0){
            this.bloques.add(new BasicBlock(blocks));//se agrega lo que llevaba
        }
    }

    /***********************************
     * generate
     ***********************************/
    public void generate(){
        this.addToCode(new CodePlain(""));
        this.addToCode(new CodeComment("",false,'#',60));

        System.out.println("***************************************");
        System.out.println("método: "+this.method.getSubname());
        System.out.println("cantidad params: "+this.method.tam_parametros);
        System.out.println("cantidad dat loc: "+this.method.tam_datos_locales);
        System.out.println("cantidad temp: "+this.method.tam_temporales);
        System.out.println("cantidad dir ret: "+this.method.tam_dir_ret);
        System.out.println("cantidad val ret: "+this.method.tam_val_ret);
        System.out.println("***************************************");


        this.addToCode(new CodeComment("Method: "+this.method.getSubname(),false));
        this.addToCode(new CodeComment("\t"+"params - "+this.method.tam_parametros+"",false));
        this.addToCode(new CodeComment("\t"+"Local Data - "+this.method.tam_datos_locales+"",false));
        this.addToCode(new CodeComment("\t"+"Temporal - "+this.method.tam_temporales+"",false));
        this.addToCode(new CodeComment("\t"+"Dir ret - "+this.method.tam_dir_ret+"",false));
        this.addToCode(new CodeComment("\t"+"Val ret - "+this.method.getRet().getType_name()+" - "+this.method.tam_val_ret,false));

        this.addToCode(new CodeComment("",false,'#',60));

        this.addToCode(new CodePlain(this.method.getSubname()+"\t"+"PROC"+"\t"+"NEAR"));

        this.addToCode(new CodePlain(""));
        this.addToCode(new CodeComment("",true,'-',25));

        int num = this.method.tam_parametros+
                this.method.tam_datos_locales+
                this.method.tam_temporales;
                //+this.method.tam_dir_ret;

        this.addToCode(new CodeOperacionUnaria("POP","DX",true));
        this.addToCode(new CodeOperacionBinaria("MOV","DI","SP"));
        this.addToCode(new CodeOperacionBinaria("MOV","[SS:DI+"+num+"]","DX"));


        this.addToCode(new CodeComment("",true,'-',25));
        this.addToCode(new CodePlain(""));


        generateCodeInstructions();

        /*for(BasicBlock a : this.bloques){
            a.generate();
            this.addToCodeAll(a.getAsmCode());
            this.addToCode(new CodePlain(";-----------------"));
            this.addToCode(new CodePlain(a.toString()));
        }*/
        

        int cant = this.method.tam_parametros+
                this.method.tam_datos_locales+
                this.method.tam_temporales;

        this.addToCode(new CodePlain(""));
        this.addToCode(new CodeComment(" METHOD END'S ",true,'-',25));
        this.addToCode(new CodeLabel(this.interMethod.getLabelEnd()));
        this.addToCode(new CodeOperacionBinaria("ADD","SP",cant+"d",true,"to POP"));
        this.addToCode(new CodePlain("RET",true));
        this.addToCode(new CodePlain(this.method.getSubname()+"\t"+"ENDP"));

        this.addToCode(new CodePlain(""));
        this.addToCode(new CodeComment("",false,'#',60));
    }

    /*****************************************
     * generateMethodCallCode
     * @param method to generate the code
     * generates all the code for a method call
     * generates push for:
     *      return value
     *      return direction
     *      all the temporal
     *      local data
     *****************************************/
    private void generateMethodCallCode(Method method) {

        //----------------------------------------------------------------------
        this.addToCode(new CodeComment(" MethodCall - "+method.getSubname()+" ",true,'-',40));

        if(method.tam_val_ret!=0){
            this.addToCode(new CodeOperacionUnaria("PUSH","0d",true,"for the return value"));
        }

        this.addToCode(new CodeOperacionUnaria("PUSH","0d",true,"for the return dir"));

        for(int i=0;i<method.tam_temporales/2;i++){
            this.addToCode(new CodeOperacionUnaria("PUSH","0d",true,"for t$_"+(method.tam_temporales/2-i)));
        }

        this.addToCode(new CodeComment(" local data space - "+(method.tam_datos_locales/2),true));
        for(int i=0;i<method.tam_datos_locales/2;i++){
            this.addToCode(new CodeOperacionUnaria("PUSH","0d"));
        }

        this.addToCode(new CodeComment(" parameters space - "+(method.tam_parametros/2),true));
        //----------------------------------------------------------------------

        this.addGananciaPila(method.tam_val_ret);
        this.addGananciaPila(method.tam_dir_ret);
        this.addGananciaPila(method.tam_temporales);
        this.addGananciaPila(method.tam_datos_locales);
        
    }

    /*****************************************
     * addGananciaPila
     * @param ganancia
     *****************************************/
    private void addGananciaPila(int ganancia){
        this.ganancia_de_pila+=ganancia;
    }

    /*****************************************
     * getGananciaPila
     * @return a string with the extra location form the stack
     *****************************************/
    private String getGananciaPila(){
        if(this.ganancia_de_pila==0){
            return "";
        }

        //return "+"+this.ganancia_de_pila;
        return "";
    }

    /*****************************************
     * getTemporalLocation
     * @param temp to locate
     * @return a position from the stack (SP)
     *****************************************/
    private String getTemporalLocation(String temp){

        String stackPos = this.interMethod.hashTemp.get(temp);

        if(stackPos.isEmpty()){
            return "0";
        }

        if(Main.expect("stack\\[(\\d)*\\]", stackPos).isEmpty()){
            //significa que lo que estaba en el hash no es una posición del stack
            return "0";
        }


        String retorno = "[SS:DI+"+ stackPos.substring(6, stackPos.length()-1) + this.getGananciaPila() + "]";
        return retorno;
    }

    /*****************************************
     * generateCodeInstruction
     * generate all the code for every instruction
     *****************************************/
    private void generateCodeInstructions(){

        for(Cod3Dir a : this.cod3dir){

            if(a instanceof interCodeGen.InterAsignacion){
                generateAsignacion((interCodeGen.InterAsignacion)a);
            }
            else if(a instanceof interCodeGen.InterComentario){
                generateComentario((interCodeGen.InterComentario)a);
            }
            else if(a instanceof interCodeGen.InterCondicional){
                generateCondicional((interCodeGen.InterCondicional)a);
            }
            else if(a instanceof interCodeGen.InterEtiqueta){
                generateEtiqueta((interCodeGen.InterEtiqueta)a);
            }
            else if(a instanceof interCodeGen.InterMethodCall){
                generateMethodCall((interCodeGen.InterMethodCall)a);
            }
            else if(a instanceof interCodeGen.InterOperacionBinaria){
                generateOperacionBinaria((interCodeGen.InterOperacionBinaria)a);
            }
            else if(a instanceof interCodeGen.InterOperacionUnaria){
                generateOperacionUnaria((interCodeGen.InterOperacionUnaria)a);
            }
            else if(a instanceof interCodeGen.InterParam){
                generateParam((interCodeGen.InterParam)a);
            }
            else if(a instanceof interCodeGen.InterPlane){
                generatePlane((interCodeGen.InterPlane)a);
            }
            else if(a instanceof interCodeGen.InterReturn){
                generateReturn((interCodeGen.InterReturn)a);
            }
            else if(a instanceof interCodeGen.InterSalto){
                generateSalto((interCodeGen.InterSalto)a);
            }
        }
    }

    /*****************************************
     * getOpcode
     * @param operador
     * get the respective opcode for the operator
     *****************************************/
    private String getOpcode(String operador){
        String retorno = "";

        if(operador.equals("/")){
            retorno = "DIV";
        }
        else if(operador.equals("%")){
            retorno = "DIV";
        }
        else if(operador.equals("*")){
            retorno = "MUL";
        }
        else if(operador.equals("+")){
            retorno = "ADD";
        }
        else if(operador.equals("-")){
            retorno = "SUB";
        }


        else if(operador.equals("==")){
            retorno = "JE";
        }
        else if(operador.equals("!=")){
            retorno = "JNE";
        }
        else if(operador.equals(">")){
            retorno = "JG";
        }
        else if(operador.equals(">=")){
            retorno = "JGE";
        }
        else if(operador.equals("<")){
            retorno = "JL";
        }
        else if(operador.equals("<=")){
            retorno = "JLE";
        }


        else{
            retorno = operador.toUpperCase();
        }
        return retorno;
    }

    /*****************************************
     * generateDirectionToRegister
     * @param dir
     * @param to_register
     * generates the code for 6 options:
     *      dir = t$_1
     *          MOV register,getTemporalDir(dir)
     *      dir = stack[literal]
     *          MOV register,[SS:DI+literal]
     *      dir = stack[temp]
     *          MOV BX,getTemporalDir(temp)
     *          MOV register,[SS:DI+BX]
     *      dir = global[literal]
     *          MOV register,GP[literal]
     *      dir = global[temp]
     *          MOV BX,getTemporalDir(temp)
     *          MOV register,GP[BX]
     *      dir = literal
     *          MOV register, dir
     *
     *****************************************/
    private void codeForDirectionToRegister(String to_register, String dir){

        if(this.isTemporal(dir)){

            this.addToCode(new CodeOperacionBinaria("MOV",to_register,this.getTemporalLocation(dir),true,to_register+" <- "+dir));

        }else if(dir.startsWith("stack")){


            String index = dir.substring(6, dir.length()-1);

            //dos opciones:
            //  index = literal
            //  index = registro


            if(this.isTemporal(index)){

                //MOV   BX, [SS:DI+2]
                //MOV   to_register,[SS:DI+BX]
                this.addToCode(new CodeOperacionBinaria("MOV","BX",this.getTemporalLocation(index)));
                this.addToCode(new CodeOperacionBinaria("MOV",to_register,"[SS:DI+BX"+this.getGananciaPila()+"]",true,to_register+" <- "+dir));


            }else{
                //el index es literal

                this.addToCode(new CodeOperacionBinaria("MOV",to_register,"[SS:DI+"+index+this.getGananciaPila()+"]",true,to_register+" <- "+dir));

            }


        }else if(dir.startsWith("global")){

            String index = dir.substring(7, dir.length()-1);

            //dos opciones:
            //  index = literal
            //  index = registro


            if(this.isTemporal(index)){

                //MOV   BX, [SS:DI+2]
                //MOV   to_register,GP[BX]
                this.addToCode(new CodeOperacionBinaria("MOV","BX",this.getTemporalLocation(index)));
                this.addToCode(new CodeOperacionBinaria("MOV",to_register,"GP[BX"+this.getGananciaPila()+"]",true,to_register+" <- "+dir));


            }else{
                //el index es literal

                this.addToCode(new CodeOperacionBinaria("MOV",to_register,"GP["+index+this.getGananciaPila()+"]",true,to_register+" <- "+dir));

            }


        }else{

            //es literal

            this.addToCode(new CodeOperacionBinaria("MOV",to_register,""+dir,true,to_register+" <- "+dir));
        }

    }

    /*****************************************
     * generateDirectionToRegister
     * @param dir
     * @param to_register
     * generates the code for 5 options:
     *      dir = t$_1
     *          MOV getTemporalDir(dir),register
     *      dir = stack[literal]
     *          MOV [SS:DI+literal],register
     *      dir = stack[temp]
     *          MOV BX,getTemporalDir(temp)
     *          MOV [SS:DI+BX],register
     *      dir = global[literal]
     *          MOV GP[literal],register
     *      dir = global[temp]
     *          MOV BX,getTemporalDir(temp)
     *          MOV GP[BX],register
     *****************************************/
    private void codeForRegisterToDirection(String dir, String register){

        if(this.isTemporal(dir)){

            this.addToCode(new CodeOperacionBinaria("MOV",this.getTemporalLocation(dir),register,true,dir+" <- "+register));

        }else if(dir.startsWith("stack")){


            String index = dir.substring(6, dir.length()-1);

            //dos opciones:
            //  index = literal
            //  index = registro

            if(this.isTemporal(index)){

                //MOV   BX, [SS:DI+2]
                //MOV   [SS:DI+BX],to_register
                this.addToCode(new CodeOperacionBinaria("MOV","BX",this.getTemporalLocation(index)));
                this.addToCode(new CodeOperacionBinaria("MOV","[SS:DI+BX"+this.getGananciaPila()+"]",register,true,dir+" <- "+register));


            }else{
                //el index es literal

                this.addToCode(new CodeOperacionBinaria("MOV","[SS:DI+"+index+this.getGananciaPila()+"]",register,true,dir+" <- "+register));

            }


        }else if(dir.startsWith("global")){

            String index = dir.substring(7, dir.length()-1);

            //dos opciones:
            //  index = literal
            //  index = registro


            if(this.isTemporal(index)){

                //MOV   BX, [SS:DI+2]
                //MOV   to_register,GP[BX]
                this.addToCode(new CodeOperacionBinaria("MOV","BX",this.getTemporalLocation(index)));
                this.addToCode(new CodeOperacionBinaria("MOV","GP[BX"+this.getGananciaPila()+"]",register,true,dir+" <- "+register));


            }else{
                //el index es literal

                this.addToCode(new CodeOperacionBinaria("MOV","GP["+index+this.getGananciaPila()+"]",register,true,dir+" <- "+register));

            }


        }else{

            //es literal

            this.addToCode(new CodePlain("ERROR!!! - generateRegisterToDirection - literal"));
        }

    }



//*****************************************************************************************************************

    /*****************************************
     * generateSalto
     * generate a jump in assembler
     *****************************************/
    private void generateSalto(InterSalto interSalto) {
        this.addToCode(new CodeJump("JMP",interSalto.getEtiqueta()));
    }

    /*****************************************
     * generateComentario
     * copy the comment
     *****************************************/
    private void generateComentario(InterComentario interComentario) {

        if(interComentario.getComentario().startsWith("+")){
            return;
        }

        this.addToCode(new CodeComment(interComentario.getComentario(),interComentario.getTab()));
    }

    /*****************************************
     * generateEtiqueta
     * copy the label
     *****************************************/
    private void generateEtiqueta(InterEtiqueta interEtiqueta) {
        this.addToCode(new CodeLabel(interEtiqueta.getEtiqueta()));
    }

    /*****************************************
     * generateMethodCall
     * generate the instructions for a methodCall
     *****************************************/
    private void generateMethodCall(InterMethodCall interMethodCall) {

        //obtener el nombre de la función a llamar
        String subname = interMethodCall.getNombre_funcion();
        //se obtiene el método de la tabla de métodos
        Method met = this.interMethod.parser.getMethodTable().getMethodBySubname(subname);

        //ver si no tiene parámetros
        if(interMethodCall.getCant_params().equals("0")){

            //se genera el código preliminar para ese método
            this.generateMethodCallCode(met);
        }


        this.addToCode(new CodePlain(""));
        this.addToCode(new CodeOperacionUnaria("CALL",interMethodCall.getNombre_funcion()));


        this.addGananciaPila(-1*met.tam_parametros);
        this.addGananciaPila(-1*met.tam_datos_locales);
        this.addGananciaPila(-1*met.tam_temporales);
        this.addGananciaPila(-1*met.tam_dir_ret);

        boolean isVoid = interMethodCall.isVoid_type();

        if(!isVoid){

            String t1 = interMethodCall.getTemp_retorno();

            this.addToCode(new CodeOperacionUnaria("POP","DX",true,"return value"));

            this.addGananciaPila(-1*met.tam_val_ret);
            
            this.addToCode(new CodeOperacionBinaria("MOV","DI","SP",true,"return DI to this method"));

            this.addToCode(new CodeOperacionBinaria("MOV",getTemporalLocation(t1),"DX",true,t1+" <- DX"));

        }else{

            this.addToCode(new CodeOperacionBinaria("MOV","DI","SP",true,"return DI to this method"));
            
        }
        
        this.addToCode(new CodeComment(" methodCall end - "+interMethodCall.getNombre_funcion()+" ",true,'-',40));

    }

    /*****************************************
     * generateParam
     * generate the instructions for a parameter
     * generate also if needs all the push
     *****************************************/
    private void generateParam(InterParam interParam) {

        String method_subname_to_call = interParam.getFrom_funtion();
        int num = interParam.getNum_of_parameter();

        String t1 = interParam.getParam();

        if(num == 1){
            //es el primer parámetro, entonces hay que hacer varios push para alocar espacio
            Method method_to_call = this.interMethod.parser.getMethodTable().getMethodBySubname(method_subname_to_call);
            generateMethodCallCode(method_to_call);
        }

        if(isTemporal(t1)){

            //NO es literal.. es un temporal

            //calcular la dirección del temporal
            //pasar del temporal a un registro
            this.addToCode(new CodeOperacionBinaria("MOV","DX",this.getTemporalLocation(t1),true,"DX <- "+t1));
            //hacer push del registro
            this.addToCode(new CodeOperacionUnaria("PUSH","DX",true,"param temporal - "+method_subname_to_call+" - "+num));

        }
        else{

            //es un literal
            this.addToCode(new CodeOperacionUnaria("PUSH",t1,true,"param literal - "+method_subname_to_call+" - "+num));

        }

        this.addGananciaPila(2);
        
        
    }

    /*****************************************
     * generateReturn
     * save in the correct direction
     *****************************************/
    private void generateReturn(InterReturn interReturn) {


        String t1 = interReturn.getRetorno();

        int pos = this.method.tam_parametros;
        pos += this.method.tam_datos_locales;
        pos += this.method.tam_temporales;
        pos += this.method.tam_dir_ret;

        String return_pos = "[SS:DI+"+pos+this.getGananciaPila()+"]";
        String from = t1;

        String parte = "WORD PTR "; //si es una literal

        if(this.isTemporal(t1)){

            from = "DX";
            this.addToCode(new CodeOperacionBinaria("MOV",from,this.getTemporalLocation(t1),true,from+" <- "+t1));
            parte = "";
        }



        this.addToCode(new CodeOperacionBinaria("MOV",return_pos,parte+from,true,"return_dir <- "+from));
    }

    /*****************************************
     * generateAsignacion
     * generates the moves for an assign
     *****************************************/
    private void generateAsignacion(InterAsignacion interAsignacion) {

        String dir1 = interAsignacion.getDir1();
        String dir2 = interAsignacion.getDir2();

        //dir1 sólo puede ser: temporal, stack[num], stack[temp], global[num], global[temp]
        //dir1 sólo puede ser: temporal, stack[num], stack[temp], global[num], global[temp], literal

        String register = "AX";

        this.codeForDirectionToRegister(register,dir2);
        this.codeForRegisterToDirection(dir1, register);

    }

    /*****************************************
     * generateOperacionBinaria
     * generate the instructions for a binary operation
     *****************************************/
    private void generateOperacionBinaria(InterOperacionBinaria interOperacionBinaria) {

        //TODO agregar comentario en la operación binaria

        String dir1 = interOperacionBinaria.getDir1();
        String dir2 = interOperacionBinaria.getDir2();
        String dir3 = interOperacionBinaria.getDir3();
        String operador = interOperacionBinaria.getOperador();

        String opcode = this.getOpcode(operador);

        if(opcode.equals("DIV")){
            //DIV División (sin signo) - DIV Op - AX := DX:AX/Op - DX:=Resto

            this.codeForDirectionToRegister("CX", dir3);
            this.codeForDirectionToRegister("AX", dir2);
            this.addToCode(new CodeOperacionBinaria("XOR","DX","DX"));
            this.addToCode(new CodeOperacionUnaria("DIV","CX"));

            if(operador.equals("/")){
                //el resultado de la división está en AX
                this.codeForRegisterToDirection(dir1, "AX");

            }else if(operador.equals("%")){
                //el residuo de la división está en DX
                this.codeForRegisterToDirection(dir1, "DX");

            }
            return;
        }

        if(opcode.equals("MUL")){
            //MUL Multiplicación (sin signo) MUL Op - DX:AX := AX*Op
            if(operador.equals("*")){

                this.codeForDirectionToRegister("CX", dir3);
                this.codeForDirectionToRegister("AX", dir2);
                this.addToCode(new CodeOperacionUnaria("MUL","CX"));
                this.addToCode(new CodeOperacionBinaria("XOR","DX","DX"));

                this.codeForRegisterToDirection(dir1, "AX");

            }
            return;
        }

        this.codeForDirectionToRegister("DX", dir3);
        this.codeForDirectionToRegister("CX", dir2);
        this.addToCode(new CodeOperacionBinaria(opcode,"CX","DX"));
        this.codeForRegisterToDirection(dir1, "CX");
    }

    /*****************************************
     * generateOperacionUnaria
     * generate the instructions for a operation
     *****************************************/
    private void generateOperacionUnaria(InterOperacionUnaria interOperacionUnaria) {

        //TODO poner comentarios en las operaciones unarias

        String dir1 = interOperacionUnaria.getDir1();
        String dir2 = interOperacionUnaria.getDir2();

        String operador = interOperacionUnaria.getOperador();

        String opcode = this.getOpcode(operador);

        this.codeForDirectionToRegister("CX", dir2);
        this.addToCode(new CodeOperacionUnaria(opcode,"CX"));
        this.codeForRegisterToDirection(dir1, "CX");

    }

//*****************************************************************************************************************








    /*****************************************
     * generatePlane
     * copy the instruction
     *****************************************/
    private void generatePlane(InterPlane interPlane) {
        System.out.println("generatePlane: Not yet implemented");
        System.out.println("generatePlane: "+interPlane.getCodeString());
    }

    /*****************************************
     * generateCondicional
     * generate the instructions for a conditional
     *****************************************/
    private void generateCondicional(InterCondicional interCondicional) {
        //CMP Comparar CMP Op1,Op2 Op1-Op2
        //JE Saltar si es igual
        //JNE Saltar si no es igual
        //JG Saltar si es mayor
        //JGE Saltar si es mayor o igual
        //JL Saltar si es menor
        //JLE Saltar si es menor o igual
        //JS Saltar si hay signo (=negativo)


        String dir1 = interCondicional.getDir1();
        String dir2 = interCondicional.getDir2();
        String label = interCondicional.getEtiqueta();
        String operador = interCondicional.getOperador();
        
        String opcode = this.getOpcode(operador);
        String comment = "";
        if(opcode.equals("JE")){
            comment = "==";
        }else if(opcode.equals("JNE")){
            comment = "!=";
        }else if(opcode.equals("JG")){
            comment = ">";
        }else if(opcode.equals("JGE")){
            comment = ">=";
        }else if(opcode.equals("JL")){
            comment = "<";
        }else if(opcode.equals("JLE")){
            comment = "<=";
        }else if(opcode.equals("JS")){
            comment = "val < 0";
        }


        String L1 = this.interMethod.newLabel();
        String L2 = this.interMethod.newLabel();


        this.codeForDirectionToRegister("AX", dir1);
        this.codeForDirectionToRegister("CX", dir2);


        this.addToCode(new CodeOperacionBinaria("CMP","AX","CX"));

        
        this.addToCode(new CodeOperacionUnaria(opcode,L1,true,comment));


        this.addToCode(new CodeOperacionUnaria("JMP",L2));
        this.addToCode(new CodeLabel(L1));
        this.addToCode(new CodeOperacionUnaria("JMP",label));
        this.addToCode(new CodeLabel(L2));
        
    }
}
